package cn.taobaoke.restful.domain;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * 订单表数据层。
 * 订单表采用分表的方式，前缀采用tb_order_，后缀表示具体的分表项。
 * 如tb_order_c001表示c001所拥有的订单表。
 */
@Repository
public class OrderV2Repository {

    @PersistenceContext
    private EntityManager entityManager;

    private static final String query = "SELECT * FROM tb_order_"; // 拼接具体的订单表

    public List<OrderEntity1> getOrders(String domain) {
        String sql = query + domain;
        Query query = entityManager.createNativeQuery(sql, OrderEntity1.class);
        return query.getResultList();
    }

    /**
     * 根据订单编号查询订单是否存在。
     * @param orderNumber 订单编号
     * @param domain 分表的后缀 `tb_order_${domain}`
     * @return Optional
     */
    public Optional<OrderEntity1> findByOrderNumber(String orderNumber, String domain) {
        String sql = query + domain + " WHERE order_number = :orderNumber";
        Query query = entityManager.createNativeQuery(sql, OrderEntity1.class);
        query.setParameter("orderNumber", orderNumber);
        List result = query.getResultList();
        if (result.size() != 0) {
            return Optional.of((OrderEntity1) result.get(0));
        }
        return Optional.empty();
    }

    /**
     * 模糊查询代理的订单列表。
     * @param agentId 代理ID
     * @param keyword 关键字
     * @param domain 分表的后缀 `tb_order_${domain}`
     * @param pageable 分页信息
     * @return 分页信息
     */
    public Page<OrderEntity1> findOrdersForAgentByKeyword(Long agentId, String keyword, String domain, Pageable pageable) {
        String sql = query + domain + " WHERE (order_number LIKE :keyword OR commodity_info LIKE :keyword) AND ( grand_parent_id = :agentId OR parent_id = :agentId OR promoter_id = :agentId )";
        Query query = entityManager.createNativeQuery(sql);
        query.setParameter("keyword", "%" + keyword + "%");
        query.setParameter("agentId", agentId);

        int count = query.getResultList().size();
        int pageNumber = pageable.getPageNumber();
        int size = pageable.getPageSize();
        query.setFirstResult(pageNumber * size);
        query.setMaxResults(size);

        Page<OrderEntity1> page = new PageImpl<OrderEntity1>(query.getResultList(), pageable, count);
        return page;
    }

    /**
     * 模糊查询订单列表
     * @param keyword 关键字
     * @param domain 分表的后缀 `tb_order_${domain}`
     * @param pageable 分页信息
     * @return 分页信息
     */
    public Page<OrderEntity1> findOrdersByKeyword(String keyword, String domain, Pageable pageable) {
        String sql = query + domain + " WHERE (order_number LIKE :keyword OR commodity_info LIKE :keyword)";

        Query query = entityManager.createNativeQuery(sql, OrderEntity1.class);
        query.setParameter("keyword", "%" + keyword + "%");
        int count = query.getResultList().size();
        int pageNumber = pageable.getPageNumber();
        int size = pageable.getPageSize();
        query.setFirstResult(pageNumber * size);
        query.setMaxResults(size);

        Page<OrderEntity1> page = new PageImpl<OrderEntity1>(query.getResultList(), pageable, count);
        return page;
    }

    @Transactional
    public int save(OrderEntity1 orderEntity, String domain) {
        if (orderEntity.getId() == null) // 插入
            return saveAll(Arrays.asList(orderEntity), domain);
        else // 更新
            return updateAll(Arrays.asList(orderEntity), domain);
    }

    /**
     * 插入订单。
     * @param orderEntities 保存的订单列表
     * @param domain 分表的后缀 `tb_order_${domain}`
     * @return 插入的条数
     */
    @Transactional
    public int saveAll(List<OrderEntity1> orderEntities, String domain) {
        entityManager.setFlushMode(FlushModeType.COMMIT);
        String sql = "INSERT INTO tb_order_" + domain +
                " (ad_position_id, admin_amount, ali_wangwang, category_name, click_time, commission_amount, commission_rate, commodity_id, commodity_info, commodity_num, commodity_price, create_time, effect_prediction, estimated_income, grand_parent_amount, grand_parent_id, income_ratio, media_id, media_name, order_number, order_status, order_type, parent_amount, parent_id, payment, pid, pid_name, promoter_amount, promoter_id, settlement_amount, settlement_time, share_ratio, shop, subsidy_amount, subsidy_ratio, subsidy_type, third_party, transaction_platform, domain_id) " +
                "values (:ad_position_id, :admin_amount, :ali_wangwang, :category_name, :click_time, :commission_amount, :commission_rate, :commodity_id, :commodity_info, :commodity_num, :commodity_price, :create_time, :effect_prediction, :estimated_income, :grand_parent_amount, :grand_parent_id, :income_ratio, :media_id, :media_name, :order_number, :order_status, :order_type, :parent_amount, :parent_id, :payment, :pid, :pid_name, :promoter_amount, :promoter_id, :settlement_amount, :settlement_time, :share_ratio, :shop, :subsidy_amount, :subsidy_ratio, :subsidy_type, :third_party, :transaction_platform, :domain_id)";

        Query query = entityManager.createNativeQuery(sql);
        int cnt = 0;
        for (OrderEntity1 entity : orderEntities) {
            setOrderParameters(query, entity);
            cnt += query.executeUpdate();
        }
        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return cnt;
    }

    /**
     * 根据订单编号更新订单信息。
     * @param orderEntities 待更新的订单列表
     * @param domain 分表的后缀 `tb_order_${domain}`
     * @return 更新的条数
     */
    @Transactional
    public int updateAll(List<OrderEntity1> orderEntities, String domain) {
        entityManager.setFlushMode(FlushModeType.COMMIT);
        String sql = "UPDATE tb_order_" + domain + " SET " +
                "ad_position_id = :ad_position_id, admin_amount = :admin_amount, ali_wangwang = :ali_wangwang, category_name = :category_name, click_time = :click_time, commission_amount = :commission_amount, commission_rate = :commission_rate, commodity_id = :commodity_id, commodity_info = :commodity_info, commodity_num = :commodity_num, commodity_price = :commodity_price, create_time = :create_time, effect_prediction = :effect_prediction, estimated_income = :estimated_income, grand_parent_amount = :grand_parent_amount, grand_parent_id = :grand_parent_id, income_ratio = :income_ratio, media_id = :media_id, media_name = :media_name, order_status = :order_status, order_type = :order_type, parent_amount = :parent_amount, parent_id = :parent_id, payment = :payment, pid = :pid, pid_name = :pid_name, promoter_amount = :promoter_amount, promoter_id = :promoter_id, settlement_amount = :settlement_amount, settlement_time = :settlement_time, share_ratio = :share_ratio, shop = :shop, subsidy_amount = :subsidy_amount, subsidy_ratio = :subsidy_ratio, subsidy_type = :subsidy_type, third_party = :third_party, transaction_platform = :transaction_platform, domain_id = :domain_id, order_number = :order_number " +
                "WHERE id = :id";

        Query query = entityManager.createNativeQuery(sql);
        int cnt = 0;
        for (OrderEntity1 entity : orderEntities) {
            setOrderParameters(query, entity);
            query.setParameter("id", entity.getId());
            cnt += query.executeUpdate();
        }
        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return cnt;
    }

    // 订单查询参数设置
    private void setOrderParameters(Query query, OrderEntity1 entity) {
        query.setParameter("ad_position_id", entity.getAdPositionId());
        query.setParameter("admin_amount", entity.getAdminAmount());
        query.setParameter("ali_wangwang", entity.getAliWangwang());
        query.setParameter("category_name", entity.getCategoryName());
        query.setParameter("click_time", entity.getClickTime());
        query.setParameter("commission_amount", entity.getCommissionAmount());
        query.setParameter("commission_rate", entity.getCommissionRate());
        query.setParameter("commodity_id", entity.getCommodityId());
        query.setParameter("commodity_info", entity.getCommodityInfo());
        query.setParameter("commodity_num", entity.getCommodityNum());
        query.setParameter("commodity_price", entity.getCommodityPrice());
        query.setParameter("create_time", entity.getCreateTime());
        query.setParameter("effect_prediction", entity.getEffectPrediction());
        query.setParameter("estimated_income", entity.getEstimatedIncome());
        query.setParameter("grand_parent_amount", entity.getGrandParentAmount());
        query.setParameter("grand_parent_id", entity.getGrandParentId());
        query.setParameter("income_ratio", entity.getIncomeRatio());
        query.setParameter("media_id", entity.getMediaId());
        query.setParameter("media_name", entity.getMediaName());
        query.setParameter("order_number", entity.getOrderNumber());
        query.setParameter("order_status", entity.getOrderStatus());
        query.setParameter("order_type", entity.getOrderType());
        query.setParameter("parent_amount", entity.getParentAmount());
        query.setParameter("parent_id", entity.getParentId());
        query.setParameter("payment", entity.getPayment());
        query.setParameter("pid", entity.getPid());
        query.setParameter("pid_name", entity.getPidName());
        query.setParameter("promoter_amount", entity.getPromoterAmount());
        query.setParameter("promoter_id", entity.getPromoterId());
        query.setParameter("settlement_amount", entity.getSettlementAmount());
        query.setParameter("settlement_time", entity.getSettlementTime());
        query.setParameter("share_ratio", entity.getShareRatio());
        query.setParameter("shop", entity.getShop());
        query.setParameter("subsidy_amount", entity.getSubsidyAmount());
        query.setParameter("subsidy_ratio", entity.getSubsidyRatio());
        query.setParameter("subsidy_type", entity.getSubsidyType());
        query.setParameter("third_party", entity.getThirdParty());
        query.setParameter("transaction_platform", entity.getTransactionPlatform());
        query.setParameter("domain_id", entity.getDomainId());
    }
}
